home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Tool Chest / Development Tools & Languages / • Other Platforms / PCCTS 1.31 / Documentation / UPDAT120.txt < prev    next >
Encoding:
Text File  |  1995-03-10  |  35.9 KB  |  1,523 lines  |  [TEXT/MPS ]

  1. PCCTS 1.20 --- Release Notes
  2.  
  3. Terence J. Parr
  4. University of Minnesota 
  5. Army High-Performance Computing 
  6. Research Center 
  7. Minneapolis, MN 55415 
  8. parrt@acm.org 
  9.  
  10. Russell W. Quong 
  11. School of Electrical Engineering 
  12. Purdue University
  13. W. Lafayette, IN 47907
  14. quong@ecn.purdue.edu 
  15.  
  16.  
  17. William E. Cohen 
  18. School of Electrical Engineering 
  19. Purdue University
  20. W. Lafayette, IN 47907
  21. cohenw@ecn.purdue.edu 
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29. This document describes the 1.20 release of the Purdue Compiler
  30. Construction Tool Set (PCCTS).  A number of new features have been
  31. added since 1.10 (August 1993), but the main addition is the
  32. introduction of C++ support.  The C++ support will be described in a
  33. forthcoming paper---it is merely summarized here.
  34.  
  35. PCCTS is in the public-domain and can be obtained at 
  36. marvin.ecn.purdue.edu in pub/pccts/1.20.  You can join the 
  37. pccts-users mailing list dealing with tools ANTLR, DLG (and SORCERER)
  38. by emailing pccts-users-request@ahpcrc.umn.edu with a body of
  39. subscribe pccts-users your-name-or-ret-addr.
  40.  
  41. The authors make no claims that this software will do what you want,
  42. that this manual is any good, or that the software actually
  43. works---use PCCTS at your own risk.  Bug reports and/or cheery reports
  44. of its usefulness are very welcome, however.
  45.  
  46.  
  47. [This file was automatically converted from the LaTeX source; please
  48.  see the Postscript version of this file where possible].
  49.  
  50. Introduction
  51.  
  52. The 1.20 release is primarily to introduce C++ support for PCCTS, but
  53. includes some nice overall enhancements and important bug fixes.  The
  54. C++ support is only of  quality and, as such, can be expected to
  55. change in future releases.
  56.  
  57. We anticipate more frequent releases to PCCTS in the future rather
  58. than big, twice-a-year, releases to provide faster bug fixes and
  59. feature enhancements.
  60.  
  61. The main 1.20 features and enhancements are
  62.  
  63.  
  64.  
  65.  
  66. Added ``tokclass'' (define a set of tokens), ``.''
  67. (wildcard operator), ``~'' (not operator).
  68.  
  69. Added ``..'' token range operator.
  70.  
  71. Added ``tokdefs'' so programmers can have predefined token type
  72. values.
  73.  
  74. A new, improved genmk program.
  75.  
  76. Line numbers are now tracked when using infinite lookahead.
  77.  
  78. Added C++ support for ANTLR and DLG output.
  79.  
  80. Added ``-o '' option to specify where all output should go.
  81.  
  82. A few nasty code generation bugs were fixed as well as a few bugs
  83. relating to semantic predicate hoisting.
  84.  
  85.  
  86.  
  87. Token Classes
  88.  
  89. A token class is set of tokens that can be referenced as one entity;
  90. they are equivalent to a subrule consisting of its member tokens
  91. separated by ``''s.  The basic syntax is:
  92.  
  93.  
  94. tokclass    
  95.  
  96.  
  97.  
  98. where  is a token reference (either a token label or a regular
  99. expression in double-quotes) or a token class reference; token classes
  100. may have overlapping tokens.
  101.  
  102. The difference between a token class and a subule lies in efficiency.
  103. A reference to a token class is a simple set membership test during
  104. parser execution rather than a linear search of the tokens in a
  105. subrule.  Furthermore, the set membership will be much smaller than a
  106. series of if-statements in a recursive-descent parser.  Note that
  107. automaton-based parsers (both  and ) automatically perform
  108. this type of set membership (specifically, a table lookup), but lack
  109. the flexibility of recursive-descent parsers such as those constructed
  110. by ANTLR.
  111.  
  112. Figure  is a sample ANTLR 1.20 program that
  113. recognizes a simple mythical assembly language with statements such as:
  114.  
  115.  
  116. segment data
  117. a  ds 42
  118. b  ds 13
  119. segment code
  120.    load r1, a
  121.    load r2, b
  122.    add  r1,r2,r3
  123.    print r3
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164. Referencing token class REGISTER is the same as referencing
  165.  
  166.  
  167. ( "r0"  "r1"  "r2"  "r3" )
  168.  
  169.  
  170. A wildcard token is also available that refers to an implied token
  171. class consisting of all tokens referenced within a grammar.  It can be
  172. used to ignore pieces of the input:
  173.  
  174.  
  175. ig  :   "beginignore"
  176.         .
  177.         "endignore"
  178.     ;
  179.  
  180.  
  181.  
  182. which matches any single token between beginignore and
  183. endignore, or the wildcard can be used for error detection:
  184.  
  185.  
  186. if  :   "if" expr "then" stat
  187.        .       <<fprintf(stderr, "malformed if-statement");>>
  188.     ;
  189.  
  190.  
  191. The programmer should be careful not to do things like this:
  192.  
  193.  
  194. ig  :   "beginignore"
  195.         ( . )*
  196.         "endignore"
  197.     ;
  198.  
  199.  
  200.  
  201. because the loop generated for the ( . )* block will never
  202. terminate---"endignore" is also matched by the wildcard.
  203.  
  204. Rather than using the wildcard to match large token classes, it is
  205. often best to use the  operator.  For example,
  206.  
  207.  
  208. ig  :   "beginignore"
  209.         (  "endignore" )*
  210.         "endignore"
  211.     ;
  212.  
  213.  
  214.  
  215. where   is the  operator.  The if example
  216. could be rewritten as:
  217.  
  218.  
  219. if  :   "if" expr "then" stat
  220.         "if"    <<fprintf(stderr, "malformed if-statement");>>
  221.     ;
  222.  
  223.  
  224. The  operator may be applied to token class references and token
  225. references only (it may not be applied to subrules, for example).
  226.  
  227. The wildcard operator and the  operator never result in a set
  228. containing the end-of-file token type.
  229.  
  230. One final token operator has been introduced---the range operator of
  231. the form ...  The vaue of  must be less than
  232.  and the values in between should be valid token types.  In
  233. general, this feature should be used in conjunction with 
  234. tokdefs so that the programmer controls the token type values.
  235.  
  236. An example range operator is:
  237.  
  238.  
  239. tokdefs "mytokens.h"
  240.  
  241. a : OpStart .. OpEnd operand ;
  242.  
  243.  
  244. This feature is perhaps unneeded due to the more powerful token class
  245. directive.
  246.  
  247. New Directive tokdefs
  248.  
  249. It is often the case that the user is interested in specifying the
  250. token types rather than having ANTLR generate its own; typically, this
  251. situation arises when the user wants to link an ANTLR-generated parser
  252. with a non-DLG-based scanner.  To get ANTLR to use pre-assigned token
  253. types, specify
  254.  
  255.  
  256. tokdefs ""
  257.  
  258.  
  259.  
  260. before any token definitions where  is a file with only a
  261. list of defines or an enum definition with optional
  262. comments.
  263.  
  264. When this directive is used, new token label definitions will not be
  265. allowed (either explicit definitions like token A or implicit
  266. definitions such as a reference to a token label in a rule).  However,
  267. the programmer may attach regular expressions and lexical actions to
  268. the token labels defined in .  For example, if 
  269. contained:
  270.  
  271.  
  272. define A 2
  273.  
  274.  
  275.  
  276. and t.g contained:
  277.  
  278.  
  279. tokdefs "mytokens.h"
  280.  
  281. token A "blah"
  282.  
  283. a : A B;
  284.  
  285.  
  286.  
  287. ANTLR would report the following error message:
  288.  
  289.  
  290. Antlr parser generator   Version 1.20   1989-1994
  291. t.g, line 5: error: implicit token definition not allowed with tokdefs
  292.  
  293.  
  294. New genmk
  295.  
  296. The genmk program has been substantially upgraded.  It now
  297. generates clean and scrub targets, generates more accurate
  298. file dependencies and, most importantly, generates makefiles for PCCTS
  299. C++ mode.  The command line options are defined as follows:
  300.  
  301.  
  302.  
  303. -CC: Generate C++ output from both ANTLR and DLG.
  304.  
  305. -class :  Name of the grammar class defined in the grammar
  306. files.  This is only a valid option if -CC was seen before it on
  307. the command line.
  308.  
  309. -dlg-class :  Name of DLG lexer class (default is 
  310. DLGLexer).  This is only a valid option if -CC was seen before it on
  311. the command line.  The option is placed on the DLG command line as the
  312. -cl option.
  313.  
  314. -header :  Name of the ANTLR standard header information
  315. (default=no file).
  316.  
  317. -o :  Directory where output files should go
  318. (default=".").  This is very nice for keeping the source directory
  319. clear of ANTLR and DLG spawn.
  320.  
  321. -project :  Name of executable to create (default=t).
  322.  
  323. -token-types : Token types are in this file; this option
  324. implies that the normal tokens.h is not to be generated or used
  325. for token type definitions (in C output mode, however, tokens.h may
  326. still be required because we have jammed some function prototypes in
  327. the file as well).
  328.  
  329. -trees:  Generate ASTs; basically turns on the -gt option
  330. of ANTLR, but also results in a target to compile the AST support file
  331. (in C++ mode only).
  332.  
  333. -user-lexer:  Do not create a DLG-based scanner.  Turns on ANTLR
  334. -gx command line option.  Turns off generation of targets for
  335. DLG scanners.
  336.  
  337.  
  338.  
  339. For example, to create a makefile for a grammar in test.g with
  340. project name t that uses a DLG-based scanner, use:
  341.  
  342.  
  343. genmk -project t test.g
  344.  
  345.  
  346.  
  347. To specify multiple files (comprising the same grammar) use:
  348.  
  349.  
  350. genmk -project t test.g test2.g test3.g
  351.  
  352.  
  353.  
  354. To create a basic C++ mode makefile for a grammar class Expr in
  355. file test.g and project t use:
  356.  
  357.  
  358. genmk -project t -CC -class Expr test.g
  359.  
  360.  
  361.  
  362. To rename the default DLGLexer class and (associated files) to
  363. Scanner for DLG, use:
  364.  
  365.  
  366. genmk -project t -CC -class Expr -dlg-class Scanner test.g
  367.  
  368.  
  369.  
  370. To create a makefile for a C++ parser that uses a non-DLG-based
  371. scanner, use:
  372.  
  373.  
  374. genmk -project t -CC -class Expr -user-lexer test.g
  375.  
  376.  
  377.  
  378. To create a makefile that uses a hand-built parser for a grammar that
  379. uses ``tokdefs "mytokens.h"'', use:
  380.  
  381.  
  382. genmk -project t -CC -class Expr -user-lexer -token-types mytokens.h test.g
  383.  
  384.  
  385. Line Numbers and Infinite Lookahead
  386.  
  387. Because ANTLR-generated parsers that use infinite lookahead (i.e.,
  388. syntactic predicates) scan the entire input stream before actual
  389. parsing begins, the normal line number variable zzline is
  390. meaningless---it always ``points'' to the last line in the file.  To
  391. overcome this, we have added a new macro (member function 
  392. infline(int ) in C++ mode):
  393.  
  394.  
  395. ZZINFLINE()
  396.  
  397.  
  398.  
  399. for .  ZZINFLINE(1) is the line number of the token
  400. about to be matched.  The following example illustrates the use of the
  401. new macro:
  402.  
  403.  
  404. header <<include "charbuf.h">>
  405.  
  406. <<main()  ANTLR(stat(), stdin); >>
  407.  
  408. token "[]+"        <<zzskip();>>
  409. token ""             <<zzskip(); zzline++;>>
  410. token Equal "="
  411. token Semi  ";"
  412.  
  413. stat:   (list Equal)? list Equal list ";"   <<printf("list = list");>>
  414.        list ";"                            <<printf("list");>>
  415.     ;
  416.  
  417. list:   "(" elem ("," elem)* ")"
  418.     ;
  419.  
  420. elem:   <<int line=0;>>
  421.         <<line = ZZINFLINE(1);>> WORD <<printf("WORD at line d", line);>>
  422.        <<line = ZZINFLINE(1);>> INT <<printf("INT at line d", line);>>
  423.     ;
  424.  
  425. token WORD "[a-zA-Z]+"
  426. token INT  "[0-9]+"
  427.  
  428.  
  429.  
  430.  
  431. The line number recording before the recognition of WORD and
  432. INT in elem is done because ZZINFLINE(1) refers to
  433. the line number for the token about to be matched.
  434.  
  435. This feature does not work correctly in C++ mode when -gk ANTLR
  436. option is used.
  437.  
  438. C++ Parser Organization
  439.  
  440. [The C++ Output of PCCTS 1.20 is considered only ``beta''
  441. quality.  Expect a future release to require changes in most parsers
  442. written assuming version 1.20 C++ output.]
  443.  
  444. [Also note that the C++ output has only been tested under
  445. g++ 2.5.7 and cannot be guaranteed to compile under any other C++
  446. compilers; indeed, g++ 2.4.5 will not compile our test cases.]
  447.  
  448. Computer language recognition is generally viewed conceptually as a
  449. parser that parses tokens taken from a token stream filled by a
  450. lexical analyzer (scanner) that takes characters from an input stream.
  451. In practice, the token and character streams end up being merely
  452. function calls to an input routine while the separation between parser
  453. and scanner tends to become blurred.
  454.  
  455. For the C++ output of ANTLR and DLG, we have chosen to create a class
  456. hierarchy that reflects the nice conceptual separation between
  457. recognition subtasks.  Figure  represents the class
  458. interactions that mirror the standard parsing block diagram.  In C++
  459. code, the block diagram is ``constructed'' by
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470. Attaching an input stream to a DLG-based scanner,
  471.  
  472.  
  473. DLGFileInput in(stdin); /* create an input stream for DLG to get chars from */
  474. DLGLexer scan(in,2000);/* create scanner reading from stdin w/bufsize==2000 */
  475.  
  476.  
  477.  
  478. Providing a token to DLG for it to continually fill in (the scanner is
  479. totally separated from the parser and, hence, has no idea how big the
  480. programmer's token is)Note that if C++ allowed typenames to
  481. be passed around as objects, the scanner could simply be initialized
  482. with the correct typename.  Also, since constructors cannot be virtual
  483. (polymorphic) a DLG-based token must be able to answer a message
  484. called makeToken().
  485.  
  486.  
  487. ANTLRToken aToken;
  488. scan.setToken(aToken);
  489.  
  490.  
  491.  
  492. Attaching the token stream to a parser
  493.  
  494.  
  495. Parser p(scan);
  496.  
  497.  
  498.  
  499.  
  500.  
  501. To start parsing, it is sufficient to call the Parser member
  502. function associated with the grammar rule:
  503.  
  504.  
  505. p.startingrule(anyargs);
  506.  
  507.  
  508. To specify the name of the parser class to construct, the programmer
  509. encloses all rules and actions in
  510.  
  511.  
  512. class Parser 
  513.     ...
  514.  
  515.  
  516.  
  517.  
  518. Currently, exactly one class may be defined.  For the defined class,
  519. ANTLR generates a derived class of ANTLRParser which accepts
  520. tokens (ANTLRToken) from a class derived from 
  521. ANTLRTokenBase.  This token stream can be either a user defined
  522. scanner or a DLG-based scanner.  DLG generates a class (default name
  523. is DLGLexer) that is derived from DLGLexerBase.  DLG-based
  524. scanners read input from derived classes of DLGInputStream, the
  525. most common being DLGFileInput.
  526.  
  527. Figures  and  describe the files constructed
  528. from ANTLR and DLG in C++ mode in the case where ANTLR was given a
  529. grammar called file.g containing ``class Parser ...''
  530. and DLG was given the usual parser.dlg.  If the tokdefs
  531. directive were used, then the tokens.h file would not be
  532. generated by ANTLR and if the ANTLR command line option for
  533. user-defined scanners (-gx) were used, parser.dlg would
  534. not be generated (tokdefs and -gx operate independently
  535. of each other).  Files Parser.h and Parser.C represent the
  536. class definition and support code for the output parser.  The actual
  537. recursive-descent parser generated from file.g is placed in 
  538. file.C; there may be multiple input files and for reasons of separate
  539. compilation, we do not put the parser functions into the 
  540. Parser.C file.  File tokens.h contains an enumerated type 
  541. TokenType describing the set of defined token types.  Files 
  542. DLGLexer.C and DLGLexer.h embody the class definition of the
  543. scanner described by parser.dlg.  The C++ support code for ANTLR
  544. and DLG output is not dependent on defines as the C output
  545. is.  For example, ``define DEMANDLOOK'' is not generated by
  546. ANTLR in C++ mode.  The support code senses a flag in the parser
  547. structure that indicates whether to consume lookahead on demand or to
  548. continually fill the lookahead ``pipe.''
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562. The communication medium between scanner and parser is an 
  563. ANTLRToken (the name is fixed for the class name) where the
  564. communications channel is an ANTLRTokenStream.  Tokens are no
  565. longer simply a token type; further, attributes, as defined by ANTLR
  566. 1.10, are no longer defined.  For version 1.20, we combine the previous
  567. definitions to create an abstract token, ANTLRToken under the
  568. ANTLRTokenBase hierarchy, that contains at least the token type,
  569. but may include anything else required by the user.  When using
  570. DLG-based scanners, ANTLRToken must be derived from 
  571. DLGBasedToken which adds behavior needed by DLG (DLG-based scanners
  572. need to be able to set/get the text of a token).  A common token
  573. definition, ANTLRCommonToken, is predefined to be the usual
  574. token type plus a fixed-size text buffer (similar to the old 
  575. Attrib definition in charbuf.h).  The minimal token definition
  576. is still the size of an integer (sizeof(enum TokenType)).  To
  577. access the tokens in a token stream from the parser, i
  578. variables are used.  However, these variables are consistently
  579. pointers to type ANTLRToken in C++ mode whereas in C mode 
  580. i variables are of type Attrib.
  581.  
  582. The minimal programmer-supplied code requirements to get a C++ parser
  583. going are:
  584.  
  585.  
  586.  
  587. A function that constructs the various objects in the C++ parser block
  588. diagram in Figure  and invokes one of the parser member
  589. rules in your Parser class.
  590.  
  591.  
  592. A definition for ANTLRToken.  An easy way to accomplish this is
  593. to do the following:
  594.  
  595.  
  596. typedef ANTLRCommonToken ANTLRToken;    /* a token is token type and text */
  597.  
  598.  
  599.  
  600. A class definition in the grammar file(s).
  601.  
  602.  
  603.  
  604. The various definitions need not be placed in the header
  605. action as in C output mode.  The next section provides a complete
  606. example that illustrates all of the conventions described in this
  607. section.
  608.  
  609. A Simple C++ Example
  610.  
  611. Figure  is a simple example that illustrates a simple
  612. DLG-based scanner with an ANTLR grammar class.  Assuming that the
  613. example is in a file called test.g, an executable parser may be
  614. obtained via the following command sequence:
  615.  
  616.  
  617. antlr -CC test.g
  618. dlg -CC parser.dlg
  619. C++ -c -I/usr/local/pccts/include -o test.o test.C
  620. C++ -c -I/usr/local/pccts/include -o Expr.o Expr.C
  621. C++ -c -I/usr/local/pccts/include -o DLGLexer.o DLGLexer.C
  622. C++ -o t test.o Expr.o DLGLexer.o 
  623.          /usr/local/pccts/antlrx.o 
  624.          /usr/local/pccts/dlgx.o 
  625.  
  626.  
  627.  
  628. where antlrx.o and dlgx.o are support code modules.
  629.  
  630.  
  631.  
  632.  
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666. Grammar Classes
  667.  
  668. A grammar class is defined as follows
  669.  
  670.  
  671. class Parser 
  672.     
  673.     
  674.  
  675.  
  676.  
  677.  
  678. The actions may contain any normal C++ code that is valid within a
  679. C++ class definitionActually, any normal ANTLR directive
  680. such as token definitions may be placed inside, but it is best
  681. to separate them from the grammar class.  For example,
  682.  
  683.  
  684. class Parser 
  685. <<public: int i;>>
  686. <<int f()  ; >>
  687.  
  688. rule : A B ;
  689.  
  690.  
  691.  
  692.  
  693.  
  694. would result in a C++ class definition of:
  695.  
  696.  
  697. class Parser : public ANTLRParser 
  698. protected:
  699.     static ANTLRChar *tokentbl[];
  700. private:
  701.     static SetWordType setwd1[4];
  702. private:
  703. public:
  704.     Parser(ANTLRTokenStream *lexer);
  705.     Parser(ANTLRTokenStream *lexer, TokenType eof);
  706.     void rule();
  707. public: int i;  
  708. int f()  ; 
  709. ;
  710.  
  711.  
  712. ANTLR Parser Classes
  713.  
  714. ANTLR Tokens
  715.  
  716. In C++ output mode, a token is an object that represents an
  717. abstraction of a lexical object found on the input stream by the
  718. scanner.  An ANTLR-generated parser accepts input as sequence of
  719. tokens in the form of a token stream where the token stream is usually
  720. managed by a lexical analyzer (typically DLG).  A token contains,
  721. minimally, a token type that is used by the parser to recognize
  722. grammatical structure.  Optionally, the programmer can add fields
  723. specific to the token class to carry application-specific
  724. information.  To facilitate error reporting, it is common practice to
  725. include a text string associate with each token and possibly the line
  726. number.
  727.  
  728. Figure  depicts the hierarchy of token base classes
  729. available to the programmer.  Because an ANTLR parser must be able to
  730. make local copies of input tokens, the name of the programmer's token
  731. definition is fixed to be ANTLRToken; we do this for efficiency
  732. reasons as specifying a size to the parser and then asking it to
  733. allocate memory on the heap is much slower than defining a local
  734. object on the stack.  The most basic token, ANTLRTokenBase knows
  735. how to set and get its token type and to get its text representation;
  736. the latter is needed to satisfy an ANTLR-generated parser's urge to
  737. print meaningful syntax error messages (because the text of a token is
  738. not required, this function returns the empty string unless redefined
  739. in a subclass).  ANTLRToken must have a blank constructor:
  740.  
  741.  
  742. ANTLRToken() ;
  743.  
  744.  
  745.  
  746. so that the parser can allocate local copies if required.
  747.  
  748.  
  749.  
  750.  
  751.  
  752.  
  753.  
  754. When using DLG-based scanners, additional behavior is required
  755. of a token.  DLG must be able to set the text and token type
  756. for an ANTLRToken.  A virtual function called
  757.  
  758.  
  759. virtual void makeToken(TokenType t, ANTLRChar *s);
  760.  
  761.  
  762.  
  763. is used because constructors cannot be virtual in C++ and
  764. we cannot pass the class to DLG so that it knows how to create
  765. and initialize an ANTLRToken.  It is invoked in the
  766. following manner:
  767.  
  768.  
  769. tokentofill->makeToken(gettok(), lextext);
  770.  
  771.  
  772.  
  773. where tokentofill is a pointer to an ANTLRToken.
  774. This token, again, cannot be created by DLG because it's size
  775. is unknown to the DLG support code.  It must be created by the
  776. programmer (normally just a local variable) and its address
  777. passed to the DLG-based scanner via member function 
  778. setToken().
  779.  
  780. The programmer defines an ANTLRToken class by deriving a class
  781. from DLGBasedToken (if DLG is being used---ANTLRTokenBase
  782. otherwise).  For example, a common token is provided with PCCTS:
  783.  
  784.  
  785. class ANTLRCommonToken : public DLGBasedToken 
  786. protected:
  787.     ANTLRChar text[ANTLRCommonTokenTEXTSIZE+1];
  788. public:
  789.     ANTLRCommonToken(TokenType t, ANTLRChar *s) : DLGBasedToken(t,s)
  790.              setText(s); 
  791.     ANTLRCommonToken() ;
  792.     ANTLRChar *getText()  return text; 
  793.     void setText(ANTLRChar *s)  strncpy(text, s, ANTLRCommonTokenTEXTSIZE); 
  794. ;
  795.  
  796.  
  797.  
  798. Because the parser is attached to a DLG-based scanner, the
  799. parser has access to the current input line number;
  800. consequently, the line number is not stored in this token
  801. definition.
  802.  
  803. In C output mode, a type called Attrib is defined by the
  804. programmer and a required macro zzcrattr() is invoked to
  805. set the attributes.  In C++, these items correspond to 
  806. ANTLRToken and makeToken(), respectively.
  807.  
  808. There is not a software stack of attributes or 
  809. ANTLRTokens in C++ output mode---local token copies are local
  810. variables (on the hardware stack) for efficiency and ease of
  811. debugging.
  812.  
  813. ANTLR Token Streams
  814.  
  815. In C++ mode, an ANTLR-generated parser consumes ANTLRTokens from
  816. an ANTLRTokenStream which is an object that acts like a pipeline
  817. between the parser and lexical analyzer; the lexical analyzer, in
  818. turn, consumes characters from a text-based input stream.  An 
  819. ANTLRTokenStream supplies a stream of tokens by returning the
  820. ``next'' token for each call to nextToken() and also knows how
  821. to return the current text and line number of the current token.  An
  822. ANTLRTokenStream can be anything from a simple array of 
  823. TokenTypes to a full DLG-based scanner.  Figure 
  824. depicts the token stream hierarchy.
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832. To attach a non-DLG-based scanner to an ANTLR-generated parser,
  833. the programmer subclasses ANTLRTokenStream.  For example,
  834.  
  835.  
  836. class MyTokenStream : public ANTLRTokenStream 
  837. private:
  838.    char c;
  839. public:
  840.    MyTokenStream()  c = getchar(); 
  841.    ANTLRTokenBase *nextToken();
  842. ;
  843.  
  844.  
  845.  
  846. where MyTokenStream::nextToken() is some function that
  847. embodies a lexical analyzer; i.e., it breaks up the input
  848. stream into vocabulary symbols.  nextToken() returns a
  849. pointer to an ANTLRToken that it has initialized.
  850.  
  851. ANTLR Parsers
  852.  
  853. All ANTLR-generated parsers in C++ mode are derived classes of
  854. ANTLRParser.  No preprocessor symbols are used to define
  855. the structure of the parser as is done in C mode.  In this way,
  856. the ANTLR-parser support code can be compiled separately and
  857. linked with different parsers.  The support code senses object
  858. variables such as demandlook and canuseinflook.
  859. Figure  depicts the parser class hierarchy.
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.  
  867. A few of the public interface functions are worth mentioning.
  868. To access the  token type of lookahead, use
  869.  
  870.  
  871. inline TokenType LA(int i);
  872.  
  873.  
  874.  
  875. To access a pointer to the  ANTLRToken of
  876. lookahead, use
  877.  
  878.  
  879. inline ANTLRTokenBase *LT(int i);
  880.  
  881.  
  882. When using a non-DLG-based scanner, the user must inform the
  883. parser what token type should be considered end-of-input.  This
  884. token type will then be used by the error recovery facilities
  885. to scan past bogus tokens without going beyond the end of input.
  886.  
  887.  
  888. void setEofToken(TokenType t);
  889.  
  890.  
  891. The programmer commonly wishes to modify the standard error
  892. reporting facility.  To do so in C++ mode, simply subclass 
  893. Parser and redefine syn() where Parser is your
  894. grammar class.
  895.  
  896.  
  897. void syn(ANTLRTokenBase *tok, ANTLRChar *egroup,
  898.          SetWordType *eset, TokenType etok, int k);
  899.  
  900.  
  901. When syn() is redefined, so should edecode():
  902.  
  903.  
  904. void edecode(SetWordType *);
  905.  
  906.  
  907. Upon catastrophic error, the following function is called (and
  908. should never return).  The programmer can subclass 
  909. Parser and redefine ANTLRPanic:
  910.  
  911.  
  912. void ANTLRPanic(ANTLRChar *msg);
  913.  
  914.  
  915. The following functions are the analog of the C mode infinite
  916. lookahead macros.
  917.  
  918.  
  919. int infLAvalid(int i);
  920. int infLA(int i);
  921. inline infline(int i);
  922.  
  923.  
  924. The following protected member functions can also be
  925. redefined:
  926.  
  927.  
  928. virtual void tracein(ANTLRChar *r);
  929. virtual void traceout(ANTLRChar *r);
  930.  
  931.  
  932. The various ANTLR parser class definitions could have benefited
  933. greatly from templates and multiple inheritance, but no current
  934. C++ compiler implements these reliably; i.e., because of
  935. features like this C++ is totally nonportable due to compiler
  936. limitations.
  937.  
  938. AST Classes
  939.  
  940. To use ASTs with ANTLR in C++ mode, the user simply derives a class
  941. from either ASTBase or ASTDoublyLinkedBase and adds the
  942. desired fields.  The AST classes automatically know how to do a
  943. preorder traversal of an AST, the programmer should redefine
  944.  
  945.  
  946. virtual void preorderaction()  ; 
  947. virtual void preorderbeforeaction()  printf(" ("); 
  948. virtual void preorderafteraction()  printf(" )"); 
  949.  
  950.  
  951.  
  952. in their derived class if required.  Figure  provides a
  953. simple example of how to use ASTs.
  954.  
  955. The zzmkast() and zzcrast() functions are now embodied
  956. by the AST class constructor.
  957.  
  958. -variables are used as before and are pointers to the node(s)
  959. created by token and rule references.
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.  
  990.  
  991.  
  992.  
  993.  
  994.  
  995.  
  996.  
  997.  
  998.  
  999.  
  1000.  
  1001.  
  1002.  
  1003.  
  1004.  
  1005.  
  1006.  
  1007.  
  1008.  
  1009.  
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016. DLG Classes
  1017.  
  1018. DLG generates a class (default name is DLGLexer) that is derived
  1019. from DLGLexerBase.  DLG-based scanners read input from derived
  1020. classes of DLGInputStream, the most common being 
  1021. DLGFileInput.  A number of functions can be redefined in derived
  1022. classes; the interesting ones are:
  1023.  
  1024.  
  1025.  
  1026. virtual void erraction();
  1027. void    DLGPanic(DLGChar *msg);
  1028. virtual ANTLRTokenBase *nextToken();
  1029.  
  1030.  
  1031. The nextToken() function can be redefined in a subclass so that
  1032. it knows what an ANTLRToken looks like.  The standard 
  1033. nextToken() does not have this luxury and, hence, the user is
  1034. required to provide DLG-based scanners with an ANTLRToken to
  1035. fill in.
  1036.  
  1037. The function trackColumns() can be called to turn on column
  1038. tracking.  This is analogous to setting preprocessor symbol 
  1039. ZZCOL in C mode.
  1040.  
  1041. ANTLR Parsers and Hand-Built Scanners
  1042.  
  1043. Because of the clean separation of parsing subtasks followed by ANTLR,
  1044. it is a trivial matter to link in a hand-built scanner or any
  1045. non-DLG-based scanner.  Simply turn on the -gx ANTLR command
  1046. line option, which turns off the generation of DLG input, and attach
  1047. an instance of your scanner to an instance of the parser class
  1048. generated by ANTLR.  Figures , , and 
  1049. represent a complete example.  The call to setEofToken() is done
  1050. to inform ANTLR what token type is considered end of input; this is
  1051. necessary for all hand-built parsers so that ANTLR does not try to
  1052. resynchronize, after a syntax error, beyond the end of input.
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.  
  1064.  
  1065.  
  1066.  
  1067.  
  1068.  
  1069.  
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079.  
  1080.  
  1081.  
  1082.  
  1083.  
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093.  
  1094.  
  1095.  
  1096.  
  1097.  
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105.  
  1106.  
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124.  
  1125.  
  1126.  
  1127.  
  1128.  
  1129.  
  1130.  
  1131.  
  1132.  
  1133.  
  1134.  
  1135.  
  1136.  
  1137.  
  1138.  
  1139.  
  1140.  
  1141.  
  1142. New Supplied Files
  1143.  
  1144.  
  1145.  
  1146. antlrx.h:  All ANTLR parser support
  1147. classes and the ANTLRParser class itself.
  1148.  
  1149.  
  1150. antlrx.C:  ANTLR parser support code.
  1151.  
  1152.  
  1153. dlgx.h:  DLG scanner support classes and DLGLexerBase
  1154. class.
  1155.  
  1156.  
  1157. dlgx.C:  DLG scanner support code.
  1158.  
  1159.  
  1160. astx.h:  AST class definition.
  1161.  
  1162.  
  1163. astx.C:  AST support code.
  1164.  
  1165.  
  1166. DLexer.C:  Support code that must be aware of the
  1167. particular scanner generated by DLG.  This is an ugly mechanism
  1168. and will change in future versions.
  1169.  
  1170.  
  1171. AToken.h:  Definitions for classes ANTLRTokenBase,
  1172. DLGBasedToken, and ANTLRCommonToken.
  1173.  
  1174.  
  1175. ATokenStream.h:  Definition of class 
  1176. ANTLRTokenStream.
  1177.  
  1178.  
  1179.  
  1180. -Variables in C++ Mode
  1181.  
  1182. Because attributes do not exist in C++ mode, -variables point to
  1183. ANTLRTokens.  Further, -variables do not exist for rule
  1184. references.  Rule arguments and return values should be used instead.
  1185. We anticipate the removal of -variables all together in future
  1186. releases in favor of labels for rule elements such as in the
  1187. tree-parser generator SORCERER.
  1188.  
  1189. -variables are pointers to ANTLRTokens exclusively in C++ mode.
  1190.  
  1191. Semantic Predicates
  1192.  
  1193. Semantic predicates should reference LT()->getText() instead
  1194. of LATEXT() as LATEXT does not exist.
  1195.  
  1196. Converting a 1.10 Grammar to 1.20 C++ Grammar
  1197.  
  1198. This section describes the procedure we used to convert the PCCTS 1.10
  1199. C grammar from C to C++ mode (this covers most, but not all issues);
  1200. ``your mileage may vary.''
  1201.  
  1202.  
  1203.  
  1204. Remove parser directive if any.
  1205.  
  1206.  
  1207. typedef ANTLRToken to something or derive a class.  Remove
  1208. include "charbuf.h" or other previous Attrib definition.
  1209.  
  1210.  
  1211. Add a grammar class ``wrapper'' around your grammar rules.
  1212.  
  1213.  
  1214. Convert AST stuff:  (1) make a class AST definition.  (2) Add
  1215. fields in ASTFIELDS macro to the class AST definition as
  1216. fields.  (3) Remove zzcrast and make that the constructor.
  1217. (4) Remove zzmkast if you have it and make it another
  1218. constructor (no need to convert any [args] references in the
  1219. grammar).
  1220.  
  1221.  
  1222. Add a include "DLGLexer.h" in the parser (or whatever you call
  1223. the lexical analyzer class).
  1224.  
  1225.  
  1226. Convert all  to .
  1227.  
  1228.  
  1229. Convert all LATEXT() to LT()->getText().
  1230.  
  1231.  
  1232. Definitions in header can come afterwards (i.e., do not use
  1233. the directive anymore).
  1234.  
  1235.  
  1236. Convert all 0=, =, or 
  1237. = to a return value or ``by-reference'' argument.
  1238.  
  1239.  
  1240. Convert the ANTLR() macro reference into the series of object
  1241. definitions outline in this document.
  1242.  
  1243.  
  1244.  
  1245. Semantic Predicate Hoisting
  1246.  
  1247. The hoisting of predicates in version 1.10 had a number of bugs that
  1248. have been fixed.  In addition, version 1.20 has changed the semantics
  1249. of semantic predicate hoisting slightly to gain a useful feature.
  1250. We begin by describing the bug fix.
  1251.  
  1252. The following grammar now behaves as advertised:
  1253.  
  1254.  
  1255. a : <<p1>>? b
  1256.    ID
  1257.   ;
  1258. b : <<p2>>? ID
  1259.    <<p3>>? ID
  1260.   ;
  1261.  
  1262.  
  1263. It results in the following code for a:
  1264.  
  1265.  
  1266. void a(void)
  1267.  
  1268.     ...
  1269.     if ( (LA(1)==ID)((p1)((p2)(p3))) ) 
  1270.         if (!(p1)) zzfailedpred((ANTLRChar *)"  p1"); //unused
  1271.         b();
  1272.     
  1273.     else 
  1274.         if ( (LA(1)==ID) ) 
  1275.             zzmatch(ID); zzCONSUME;
  1276.         
  1277.         else ...
  1278.  
  1279.  
  1280.  
  1281.  
  1282. Note that the following semantics indicate the correct semantic
  1283. validity of production one of a: ``p1 and (p2 or
  1284. p3).''  In version 1.10, the ``or'' was an ``and.''
  1285.  
  1286. In 1.10, we indicated that predicates were hoisting ONLY if the
  1287. grammar was syntactically ambiguous.  This had the unfortunate effect
  1288. of making it impossible to include a predicate in the loop decision for
  1289. (..)+ and (..)* subrules if only one alternative was
  1290. present.  We have changed the meaning of semantic predicates slightly
  1291. so that if only one alternative exists in a looping subrule, all
  1292. visible predicates are ALWAYS hoisting.  For example,
  1293.  
  1294.  
  1295. a : <<int i=5;>>            // match exactly 5 A's
  1296.     ( <<i>0>>? A <<i--;>> )+
  1297.   ;
  1298.  
  1299.  
  1300. In 1.10, this would have resulting in a loop that only tested the
  1301. lookahead.  In 1.20, the following is generated for the (..)+
  1302. loop:
  1303.  
  1304.  
  1305. if (((i>0))) 
  1306.     do 
  1307.         if (!(i>0)) zzfailedpred((ANTLRChar *)"  i>0"); // unused
  1308.         zzLOOP(zztasp2);
  1309.      while ( (LA(1)==A)((i>0)) );
  1310.  
  1311.  
  1312.  
  1313. C AST Changes
  1314.  
  1315. In C mode, the programmer can define the preprocessor symbol 
  1316. USERDEFINEDAST which allows the programmer to define the 
  1317. AST type themselves.  The macro ASTREQUIREDFIELDS is the
  1318. minimum set of AST fields needed by ANTLR; as such, it functions like
  1319. inheritance in C++.  For example,
  1320.  
  1321.  
  1322. typedef struct ast 
  1323.             ASTREQUIREDFIELDS;        // order is unimportant
  1324.             my stuff;
  1325.          AST;
  1326.  
  1327.  
  1328.  
  1329. The structure name must be ast for the 
  1330. ASTREQUIREDFIELDS to work.  If it is not used, the structure name
  1331. can be anything.
  1332.  
  1333. New Command-Line Options
  1334.  
  1335. The following ANTLR command line options are new:
  1336.  
  1337.  
  1338.  
  1339. -CC: Generate C++ output.
  1340.  
  1341.  
  1342. -o: Directory where output files should go (default=".").  This
  1343. is very nice for keeping the source directory clear of ANTLR and DLG
  1344. spawn.
  1345.  
  1346.  
  1347. -ct:  Do not make copies of tokens passed to the parser in C++
  1348. mode (default=to copy).  When using DLG in conjunction with ANTLR, you
  1349. will always want ANTLR to make copies because DLG only has space for
  1350. one ANTLRToken (which is passed to the scanner with 
  1351. setToken); this address is always returned and, hence, without
  1352. copies, all -variables would point to the same ANTLRToken.
  1353.  
  1354.  
  1355.  
  1356.  
  1357. The -ai option has been removed in anticipation of an ANTLR
  1358. graphical interface.
  1359.  
  1360. The following DLG command line options are new:
  1361.  
  1362.  
  1363.  
  1364. -CC: Generate C++ output.
  1365.  
  1366.  
  1367. -o: Directory where output files should go (default=".").  This
  1368. is very nice for keeping the source directory clear of ANTLR and DLG
  1369. spawn.
  1370.  
  1371.  
  1372. -cl : Specify a class name for DLG to generate.  The
  1373. default is DLGLexer.   will be a subclass of 
  1374. DLGLexerBase.
  1375.  
  1376.  
  1377.  
  1378.  
  1379. Also note that in C++ mode, DLG now does not accept the output file
  1380. name on the command line.  The class name specified (or the default of
  1381. DLGLexer) is used to derive the output file name:
  1382.  
  1383.  
  1384. dlg  
  1385.  
  1386.  
  1387. Miscellaneous New Additions
  1388.  
  1389. The following minor changes were made:
  1390.  
  1391.  
  1392.  
  1393. A new character type is used for ANTLR and DLG ANTLRChar and
  1394. DLGChar respectively in C++ mode.  Normally these are 'char',
  1395. but you can change the typedef to whatever you wish (you can
  1396. even make it a class).
  1397.  
  1398.  
  1399. ASTs were incorrectly handled in conjunction with 1.10 syntactic
  1400. predicates---this has been fixed.
  1401.  
  1402.  
  1403. The return values of rules were still assigned in guess mode (when
  1404. using syntactic predicates); the arguments are still evaluated.  This
  1405. is perhaps not too bright.
  1406.  
  1407.  
  1408. Warnings about missing header now require that -w2 ANTLR
  1409. option be set.
  1410.  
  1411.  
  1412. Allows parser to come first (before header)
  1413.  
  1414.  
  1415. Fixed a bug so that ``(A B)+ A C'' will now terminate the loop upon
  1416. ``A C'' whereas before it would just loop forever (it was not using
  1417. enough lookahead).
  1418.  
  1419.  
  1420. When a token label (for which there is no regular expression) is
  1421. referenced in a rule, a warning is generated (if the ANTLR command
  1422. line option -w2 is specified).
  1423.  
  1424.  
  1425. Fixed a nasty bug that caused ANTLR to loop forever (and a day) upon
  1426. very large grammars with lots of optional subrules.
  1427.  
  1428.  
  1429. ANTLR itself tends to give better error messages now; e.g., lexical
  1430. errors give the file now and grammatical errors (employing 
  1431. errclasses) are more readable.
  1432.  
  1433.  
  1434.  
  1435. Future
  1436.  
  1437. Our work on ANTLR continues to be heavily influenced by the feedback
  1438. from our industrial and academic user community.  As such, we are
  1439. currently developing or planning the following improvements and tools.
  1440.  
  1441.  
  1442.  
  1443.  
  1444. Good error recovery and reporting is notoriously difficult to
  1445. achieve with parser generators, especially -based tools.  We are
  1446. developing a sophisticated error handling mechanism analogous to C++
  1447. exception handling called parser exception handling that
  1448. approaches the flexibility of hand-built parsers.
  1449.  
  1450.  
  1451. The recognition strength of hand-built parsers arises from the fact
  1452. that arbitrarily-complex expressions can be used to distinguish
  1453. between alternative productions.  We will introduce a new type of
  1454. predicate called a prediction predicate that constitutes the
  1455. entire prediction expression for a particular production; i.e., ANTLR
  1456. does not generate code to test lookahead for the associated
  1457. production.  We anticipate the notation: ``<<
  1458. this-is-the-entire-prediction-expression>>?!''.
  1459.  
  1460.  
  1461. A graphical user interface is planned and a coder has been tentatively
  1462. ``pressed'' into service.  This ``GUI'' will display syntax diagrams
  1463. on the screen and, hence, ambiguities in the grammar can be
  1464. highlighted.  The output of the GUI will be an ANTLR grammar or
  1465. a PostScript representation of the syntax diagram.
  1466.  
  1467.  
  1468. We intend to yank the infinite lookahead mechanism out of 
  1469. ANTLRParser and put it in ANTLRTokenStream where it belongs.
  1470.  
  1471.  
  1472.  
  1473. [The users of PCCTS should be forewarned that we anticipate
  1474. a break with total backward compatibility for a future release
  1475. (perhaps PCCTS 2.00).  This release is intended to fix the odious C
  1476. output generated by the current version of ANTLR/DLG and will result
  1477. in a modified grammar meta-language plus the removal of some parsing
  1478. modes.  Any book on PCCTS to be written will describe this version of
  1479. reality.  Also remember that the C++ output is going to change as we
  1480. learn more about it.]
  1481.  
  1482. Acknowledgements
  1483.  
  1484. Thanks are due to Sumana Srinivasan, Mike Monegan, and Steve Naroff of
  1485. NeXT, Inc. for their extensive help in the initial definition of the
  1486. ANTLR C++ parser.  They are also instrumental in the ongoing design of
  1487. parser exception handling.
  1488.  
  1489. We thank Gary Funck at Intrepid for his extensive testing of ANTLR and
  1490. DLG plus his constant stream of excellent suggestions.
  1491.  
  1492. Steve Robenalt at Rockwell is single-handedly pushing the 
  1493. comp.compilers.pccts news group through, is helping with the
  1494. workshop, and is porting PCCTS to a number of different platforms.
  1495.  
  1496. We thank Tom Moog (moog@polhode.com) for his fantastic 
  1497. NOTES.newbie information.
  1498.  
  1499. Ariel Tamches (tamches@cs.wisc.edu) deserves credit for spending
  1500. a week of his Christmas vacation in the wilds of Minnesota helping me
  1501. with the C++ output; he developed the majority of the code for the
  1502. hand-built scanner C++ example.
  1503.  
  1504. The C++ output was also influenced by Thom Wood (
  1505. twood@tcis3.tcis.com) and Randy Helzerman helz@ecn.purdue.edu.
  1506.  
  1507. Anthony Green at Visible Decisions, John Hall at Worcester Polytechnic
  1508. Institute, Devin Hooker at Ellery Systems, Kenneth D.  Weinert at
  1509. Information Handling Services, and Roy Levow at Florida Atlantic
  1510. University helped beta test 1.20.
  1511.  
  1512. Sriram Sankar at Sun Microsystems has help debug a number of features
  1513. including the infinite lookahead line number tracking and has provided
  1514. a fix to make DLG char-size independent, which we hope to
  1515. include soon.
  1516.  
  1517. John Hall (jhall@ivy.wpi.edu) ported PCCTS to Visual C++.
  1518.  
  1519. We would also like to thank the multitude of other users of PCCTS for
  1520. their excellent suggestions and beta-testing of the new C++ parsers.
  1521.  
  1522.  
  1523.